#ifndef BSP_ARCH_ARMV8_AARCH64_PLATFORM_FT2004_H
#define BSP_ARCH_ARMV8_AARCH64_PLATFORM_FT2004_H

#ifdef __cplusplus
extern "C"
{
#endif

#define CORE0_AFF 0x0
#define CORE1_AFF 0x100
#define CORE2_AFF 0x200
#define CORE3_AFF 0x201

/*  Device register address */
#define FT_DEV_BASE_ADDR 0x28000000
#define FT_DEV_END_ADDR 0x2FFFFFFF

    /* PCI  */

#define FT_PCI_CONFIG_BASEADDR 0x40000000
#define FT_PCI_CONFIG_REG_LENGTH 0x10000000

#define FT_PCI_IO_CONFIG_BASEADDR 0x50000000
#define FT_PCI_IO_CONFIG_REG_LENGTH 0x08000000

#define FT_PCI_MEM32_BASEADDR 0x58000000
#define FT_PCI_MEM32_REG_LENGTH 0x27000000

#define FT_PCI_MEM64_BASEADDR 0x1000000000
#define FT_PCI_MEM64_REG_LENGTH 0X1000000000

#define FT_PCI_EU0_C0_CONTROL_BASEADDR 0x29000000
#define FT_PCI_EU0_C1_CONTROL_BASEADDR 0x29010000
#define FT_PCI_EU0_C2_CONTROL_BASEADDR 0x29020000
#define FT_PCI_EU1_C0_CONTROL_BASEADDR 0x29030000
#define FT_PCI_EU1_C1_CONTROL_BASEADDR 0x29040000
#define FT_PCI_EU1_C2_CONTROL_BASEADDR 0x29050000

#define FT_PCI_EU0_CONFIG_BASEADDR 0x29100000
#define FT_PCI_EU1_CONFIG_BASEADDR 0x29101000

    // timer

#define GENERIC_TIMER_CLK_FREQ_MHZ 48
/* Generic Timer */
#define GENERIC_TIMER_NS_IRQ_NUM 30
#define GENERIC_TIMER_NS_CLK_FREQ 2000000
#define COUNTS_PER_SECOND GENERIC_TIMER_NS_CLK_FREQ

/* UART */
#define FT_UART_NUM 4
#define FT_UART_REG_LENGTH 0x18000

#define FT_UART0_ID 0
#define FT_UART0_IRQ_NUM (85 + 30)
#define FT_UART0_BASE_ADDR 0x2800c000
#define FT_UART0_CLK_FREQ_HZ 100000000

#define FT_UART1_ID 1
#define FT_UART1_IRQ_NUM (86 + 30)
#define FT_UART1_BASE_ADDR 0x2800d000
#define FT_UART1_CLK_FREQ_HZ 100000000

#define FT_UART2_ID 2
#define FT_UART2_IRQ_NUM (87 + 30)
#define FT_UART2_BASE_ADDR 0x2800e000
#define FT_UART2_CLK_FREQ_HZ 100000000

#define FT_UART3_BASE_ADDR 0x2800f000
#define FT_UART3_ID 3
#define FT_UART3_IRQ_NUM (88 + 30)
#define FT_UART3_CLK_FREQ_HZ 100000000

#define FT_STDOUT_BASE_ADDR FT_UART1_BASE_ADDR
#define FT_STDIN_BASE_ADDR FT_UART1_BASE_ADDR

/****** GIC v3  *****/
#define FT_GICV3_INSTANCES_NUM 1U
#define GICV3_REG_LENGTH 0x00009000

/*
 * The maximum priority value that can be used in the GIC.
 */
#define GICV3_MAX_INTR_PRIO_VAL 240U
#define GICV3_INTR_PRIO_MASK 0x000000f0U

#define ARM_GIC_NR_IRQS 160
#define ARM_GIC_IRQ_START 0

#define ARM_GIC_IPI_COUNT 16 /* MPCore IPI count         */
#define SGI_INT_MAX 16
#define SPI_START_INT_NUM 32 /* SPI start at ID32        */
#define PPI_START_INT_NUM 16 /* PPI start at ID16        */
#define GIC_INT_MAX_NUM 1020 /* GIC max interrupts count */

#define GICV3_BASEADDRESS 0x30800000U
#define GICV3_DISTRIBUTOR_BASEADDRESS (GICV3_BASEADDRESS + 0)
#define GICV3_RD_BASEADDRESS (GICV3_BASEADDRESS + 0x80000U)

#define FT_GICV3_VECTORTABLE_NUM GIC_INT_MAX_NUM

/* GPIO */
#define GPIO0_BASE (0X28004000)
#define GPIO1_BASE (0X28005000)

#define F_GPIO_TOTAL_LINE (16)
#define F_GPIO_GROUP_NUM (2)

#define F_GPIO_PORT_MAX_NUM (2)
#define F_GPIO_PIN_MAX_NUM (16)

#define F_GPIO0_INTR_IRQ (42) // gpio0 irq number
#define F_GPIO1_INTR_IRQ (43) // gpio1 irq number

/* SPI */
#define FSPI0_BASE 0x2800c000
#define FSPI1_BASE 0x28013000
#define FSPI_FREQ 48000000
#define FSPI_DEVICE_NUM 2
#define FSPI0_IRQ_NUM 50
#define FSPI1_IRQ_NUM 51
#define FSPI0_IOMUX_CSN0_OFFSET 19
#define FSPI0_IOMUX_SCK_OFFSET 20
#define FSPI0_IOMUX_SO_OFFSET 21
#define FSPI0_IOMUX_SI_OFFSET 22

/* XMAC */
#define FT_XMAC_NUM 4

#define FT_XMAC0_ID 0
#define FT_XMAC1_ID 1
#define FT_XMAC2_ID 2
#define FT_XMAC3_ID 3

#define FT_XMAC0_BASEADDRESS 0x3200A000U
#define FT_XMAC1_BASEADDRESS 0x3200C000U
#define FT_XMAC2_BASEADDRESS 0x3200E000U
#define FT_XMAC3_BASEADDRESS 0x32010000U

#define FT_XMAC0_HOTPLUG_IRQ_NUM (53 + 30U)
#define FT_XMAC1_HOTPLUG_IRQ_NUM (54 + 30U)
#define FT_XMAC2_HOTPLUG_IRQ_NUM (55 + 30U)
#define FT_XMAC3_HOTPLUG_IRQ_NUM (56 + 30U)

#define FT_XMAC_QUEUE_MAX_NUM 8

#define FT_XMAC0_QUEUE0_IRQ_NUM (57 + 30)
#define FT_XMAC0_QUEUE1_IRQ_NUM (58 + 30)
#define FT_XMAC0_QUEUE2_IRQ_NUM (59 + 30)
#define FT_XMAC0_QUEUE3_IRQ_NUM (60 + 30)
#define FT_XMAC0_QUEUE4_IRQ_NUM (30 + 30)
#define FT_XMAC0_QUEUE5_IRQ_NUM (31 + 30)
#define FT_XMAC0_QUEUE6_IRQ_NUM (32 + 30)
#define FT_XMAC0_QUEUE7_IRQ_NUM (33 + 30)

#define FT_XMAC1_QUEUE0_IRQ_NUM (61 + 30)
#define FT_XMAC1_QUEUE1_IRQ_NUM (62 + 30)
#define FT_XMAC1_QUEUE2_IRQ_NUM (63 + 30)
#define FT_XMAC1_QUEUE3_IRQ_NUM (64 + 30)

#define FT_XMAC2_QUEUE0_IRQ_NUM (66 + 30)
#define FT_XMAC2_QUEUE1_IRQ_NUM (67 + 30)
#define FT_XMAC2_QUEUE2_IRQ_NUM (68 + 30)
#define FT_XMAC2_QUEUE3_IRQ_NUM (69 + 30)

#define FT_XMAC3_QUEUE0_IRQ_NUM (70 + 30)
#define FT_XMAC3_QUEUE1_IRQ_NUM (71 + 30)
#define FT_XMAC3_QUEUE2_IRQ_NUM (72 + 30)
#define FT_XMAC3_QUEUE3_IRQ_NUM (73 + 30)

/* CANFD */
#define FCAN_REF_CLOCK 200000000

#define FCAN_ARB_TSEG1_MIN 1
#define FCAN_ARB_TSEG1_MAX 8
#define FCAN_ARB_TSEG2_MIN 1
#define FCAN_ARB_TSEG2_MAX 8
#define FCAN_ARB_SJW_MAX 4
#define FCAN_ARB_BRP_MIN 1
#define FCAN_ARB_BRP_MAX 8192
#define FCAN_ARB_BRP_INC 1

#define FCAN_DATA_TSEG1_MIN 1
#define FCAN_DATA_TSEG1_MAX 8
#define FCAN_DATA_TSEG2_MIN 1
#define FCAN_DATA_TSEG2_MAX 8
#define FCAN_DATA_SJW_MAX 4
#define FCAN_DATA_BRP_MIN 1
#define FCAN_DATA_BRP_MAX 8192
#define FCAN_DATA_BRP_INC 1

#define FT_CAN_USE_CANFD 1

/* QSPI */
#define QSPI_NUM 1U
#define QSPI_INSTANCE 1
#define QSPI_MAX_CS_NUM 4
#define QSPI_BASEADDR 0x028008000

#define QSPI_MEM_START_ADDR 0x0
#define QSPI_MEM_END_ADDR 0x0FFFFFFF /* 256MB */
#define QSPI_MEM_START_ADDR_64 0x100000000
#define QSPI_MEM_END_ADDR_64 0x17FFFFFFF /* 2GB */

/* hw timer and tacho */
#define TIMER_TACHO_NUM 38
#define TIMER_CLK_FREQ_HZ 50000000UL /* 50MHz */
#define TIMER_TICK_PERIOD_NS 20      /* 20ns */
#define TIMER_TACHO_IRQ_ID(n) (226 + (n))
#define TIMER_TACHO_BASE_ADDR(n) (0x28054000 + 0x1000 * (n))

    // canfd

#define FCAN_REF_CLOCK 200000000

#define FCAN_ARB_TSEG1_MIN 1
#define FCAN_ARB_TSEG1_MAX 8
#define FCAN_ARB_TSEG2_MIN 1
#define FCAN_ARB_TSEG2_MAX 8
#define FCAN_ARB_SJW_MAX 4
#define FCAN_ARB_BRP_MIN 1
#define FCAN_ARB_BRP_MAX 8192
#define FCAN_ARB_BRP_INC 1

#define FCAN_DATA_TSEG1_MIN 1
#define FCAN_DATA_TSEG1_MAX 8
#define FCAN_DATA_TSEG2_MIN 1
#define FCAN_DATA_TSEG2_MAX 8
#define FCAN_DATA_SJW_MAX 4
#define FCAN_DATA_BRP_MIN 1
#define FCAN_DATA_BRP_MAX 8192
#define FCAN_DATA_BRP_INC 1

#define FT_CAN_USE_CANFD 1

    // gdma

    typedef enum
    {
        FGDMA_CH0_INDEX = 0,
        FGDMA_CH1_INDEX = 1,
        FGDMA_CH2_INDEX = 2,
        FGDMA_CH3_INDEX = 3,
        FGDMA_CH4_INDEX = 4,
        FGDMA_CH5_INDEX = 5,
        FGDMA_CH6_INDEX = 6,
        FGDMA_CH7_INDEX = 7,
        FGDMA_CH8_INDEX = 8,
        FGDMA_CH9_INDEX = 9,
        FGDMA_CH10_INDEX = 10,
        FGDMA_CH11_INDEX = 11,
        FGDMA_CH12_INDEX = 12,
        FGDMA_CH13_INDEX = 13,
        FGDMA_CH14_INDEX = 14,
        FGDMA_CH15_INDEX = 15,
        FGDMA_CH_NUM
    } FGdmaChIndex;

#define FGDMA_NUM 2
#define FGDMA_DEFAULT_PRIORITY 1

#define FGDMA_INSTANCE0 0
#define FGDMA_INSTANCE0_IRQ_NUM (236 + 30)
#define FGDMA_INSTANCE0_BASE_ADDRESS 0x32B34000
#define FGDMA_INSTANCE0_CH0_BASE_ADDRESS (FGDMA_INSTANCE0_BASE_ADDRESS + 0x20)
#define FGDMA_INSTANCE0_CH1_BASE_ADDRESS (FGDMA_INSTANCE0_CH0_BASE_ADDRESS + 0x60)
#define FGDMA_INSTANCE0_CH2_BASE_ADDRESS (FGDMA_INSTANCE0_CH1_BASE_ADDRESS + 0x60)
#define FGDMA_INSTANCE0_CH3_BASE_ADDRESS (FGDMA_INSTANCE0_CH2_BASE_ADDRESS + 0x60)
#define FGDMA_INSTANCE0_CH4_BASE_ADDRESS (FGDMA_INSTANCE0_CH3_BASE_ADDRESS + 0x60)
#define FGDMA_INSTANCE0_CH5_BASE_ADDRESS (FGDMA_INSTANCE0_CH4_BASE_ADDRESS + 0x60)
#define FGDMA_INSTANCE0_CH6_BASE_ADDRESS (FGDMA_INSTANCE0_CH5_BASE_ADDRESS + 0x60)
#define FGDMA_INSTANCE0_CH7_BASE_ADDRESS (FGDMA_INSTANCE0_CH6_BASE_ADDRESS + 0x60)
#define FGDMA_INSTANCE0_CH8_BASE_ADDRESS (FGDMA_INSTANCE0_CH7_BASE_ADDRESS + 0x60)
#define FGDMA_INSTANCE0_CH9_BASE_ADDRESS (FGDMA_INSTANCE0_CH8_BASE_ADDRESS + 0x60)
#define FGDMA_INSTANCE0_CH10_BASE_ADDRESS (FGDMA_INSTANCE0_CH9_BASE_ADDRESS + 0x60)
#define FGDMA_INSTANCE0_CH11_BASE_ADDRESS (FGDMA_INSTANCE0_CH10_BASE_ADDRESS + 0x60)
#define FGDMA_INSTANCE0_CH12_BASE_ADDRESS (FGDMA_INSTANCE0_CH11_BASE_ADDRESS + 0x60)
#define FGDMA_INSTANCE0_CH13_BASE_ADDRESS (FGDMA_INSTANCE0_CH12_BASE_ADDRESS + 0x60)
#define FGDMA_INSTANCE0_CH14_BASE_ADDRESS (FGDMA_INSTANCE0_CH13_BASE_ADDRESS + 0x60)
#define FGDMA_INSTANCE0_CH15_BASE_ADDRESS (FGDMA_INSTANCE0_CH14_BASE_ADDRESS + 0x60)

#define FGDMA_INSTANCE1 1
#define FGDMA_INSTANCE1_BASE_ADDRESS 0x32B35000
#define FGDMA_INSTANCE1_IRQ_NUM (237 + 30)
#define FGDMA_INSTANCE1_CH0_BASE_ADDRESS (FGDMA_INSTANCE1_BASE_ADDRESS + 0x20)
#define FGDMA_INSTANCE1_CH1_BASE_ADDRESS (FGDMA_INSTANCE1_CH0_BASE_ADDRESS + 0x60)
#define FGDMA_INSTANCE1_CH2_BASE_ADDRESS (FGDMA_INSTANCE1_CH1_BASE_ADDRESS + 0x60)
#define FGDMA_INSTANCE1_CH3_BASE_ADDRESS (FGDMA_INSTANCE1_CH2_BASE_ADDRESS + 0x60)
#define FGDMA_INSTANCE1_CH4_BASE_ADDRESS (FGDMA_INSTANCE1_CH3_BASE_ADDRESS + 0x60)
#define FGDMA_INSTANCE1_CH5_BASE_ADDRESS (FGDMA_INSTANCE1_CH4_BASE_ADDRESS + 0x60)
#define FGDMA_INSTANCE1_CH6_BASE_ADDRESS (FGDMA_INSTANCE1_CH5_BASE_ADDRESS + 0x60)
#define FGDMA_INSTANCE1_CH7_BASE_ADDRESS (FGDMA_INSTANCE1_CH6_BASE_ADDRESS + 0x60)
#define FGDMA_INSTANCE1_CH8_BASE_ADDRESS (FGDMA_INSTANCE1_CH7_BASE_ADDRESS + 0x60)
#define FGDMA_INSTANCE1_CH9_BASE_ADDRESS (FGDMA_INSTANCE1_CH8_BASE_ADDRESS + 0x60)
#define FGDMA_INSTANCE1_CH10_BASE_ADDRESS (FGDMA_INSTANCE1_CH9_BASE_ADDRESS + 0x60)
#define FGDMA_INSTANCE1_CH11_BASE_ADDRESS (FGDMA_INSTANCE1_CH10_BASE_ADDRESS + 0x60)
#define FGDMA_INSTANCE1_CH12_BASE_ADDRESS (FGDMA_INSTANCE1_CH11_BASE_ADDRESS + 0x60)
#define FGDMA_INSTANCE1_CH13_BASE_ADDRESS (FGDMA_INSTANCE1_CH12_BASE_ADDRESS + 0x60)
#define FGDMA_INSTANCE1_CH14_BASE_ADDRESS (FGDMA_INSTANCE1_CH13_BASE_ADDRESS + 0x60)
#define FGDMA_INSTANCE1_CH15_BASE_ADDRESS (FGDMA_INSTANCE1_CH14_BASE_ADDRESS + 0x60)

#define FT_XMAC_NUM 4

#define FT_XMAC0_ID 0
#define FT_XMAC1_ID 1
#define FT_XMAC2_ID 2
#define FT_XMAC3_ID 3

#define FT_XMAC0_BASEADDRESS 0x3200A000U
#define FT_XMAC1_BASEADDRESS 0x3200C000U
#define FT_XMAC2_BASEADDRESS 0x3200E000U
#define FT_XMAC3_BASEADDRESS 0x32010000U

#define FT_XMAC0_HOTPLUG_IRQ_NUM (53 + 30U)
#define FT_XMAC1_HOTPLUG_IRQ_NUM (54 + 30U)
#define FT_XMAC2_HOTPLUG_IRQ_NUM (55 + 30U)
#define FT_XMAC3_HOTPLUG_IRQ_NUM (56 + 30U)

#define FT_XMAC_QUEUE_MAX_NUM 8

#define FT_XMAC0_QUEUE0_IRQ_NUM (57 + 30)
#define FT_XMAC0_QUEUE1_IRQ_NUM (58 + 30)
#define FT_XMAC0_QUEUE2_IRQ_NUM (59 + 30)
#define FT_XMAC0_QUEUE3_IRQ_NUM (60 + 30)
#define FT_XMAC0_QUEUE4_IRQ_NUM (30 + 30)
#define FT_XMAC0_QUEUE5_IRQ_NUM (31 + 30)
#define FT_XMAC0_QUEUE6_IRQ_NUM (32 + 30)
#define FT_XMAC0_QUEUE7_IRQ_NUM (33 + 30)

#define FT_XMAC1_QUEUE0_IRQ_NUM (61 + 30)
#define FT_XMAC1_QUEUE1_IRQ_NUM (62 + 30)
#define FT_XMAC1_QUEUE2_IRQ_NUM (63 + 30)
#define FT_XMAC1_QUEUE3_IRQ_NUM (64 + 30)

#define FT_XMAC2_QUEUE0_IRQ_NUM (66 + 30)
#define FT_XMAC2_QUEUE1_IRQ_NUM (67 + 30)
#define FT_XMAC2_QUEUE2_IRQ_NUM (68 + 30)
#define FT_XMAC2_QUEUE3_IRQ_NUM (69 + 30)

#define FT_XMAC3_QUEUE0_IRQ_NUM (70 + 30)
#define FT_XMAC3_QUEUE1_IRQ_NUM (71 + 30)
#define FT_XMAC3_QUEUE2_IRQ_NUM (72 + 30)
#define FT_XMAC3_QUEUE3_IRQ_NUM (73 + 30)

    // canfd

#define FCAN_REF_CLOCK 200000000

#define FCAN_ARB_TSEG1_MIN 1
#define FCAN_ARB_TSEG1_MAX 8
#define FCAN_ARB_TSEG2_MIN 1
#define FCAN_ARB_TSEG2_MAX 8
#define FCAN_ARB_SJW_MAX 4
#define FCAN_ARB_BRP_MIN 1
#define FCAN_ARB_BRP_MAX 8192
#define FCAN_ARB_BRP_INC 1

#define FCAN_DATA_TSEG1_MIN 1
#define FCAN_DATA_TSEG1_MAX 8
#define FCAN_DATA_TSEG2_MIN 1
#define FCAN_DATA_TSEG2_MAX 8
#define FCAN_DATA_SJW_MAX 4
#define FCAN_DATA_BRP_MIN 1
#define FCAN_DATA_BRP_MAX 8192
#define FCAN_DATA_BRP_INC 1

#define FT_CAN_USE_CANFD 1

#define FT_CPUS_NR 4
/* WDT */
    typedef enum
    {
        WDT_INSTANCE_0 = 0,
        WDT_INSTANCE_1,
    
        WDT_INSTANCE_NUM
    } WdtInstance;


#define WDT0_REFRESH_BASE 0x28040000
#define WDT0_CONTROL_BASE 0x28041000
#define WDT1_REFRESH_BASE 0x28042000
#define WDT1_CONTROL_BASE 0x28043000

#define WDT0_INTR_IRQ 196
#define WDT1_INTR_IRQ 197

#define WDT_CLK 48000000 /* 48MHz */


/* SDIO */
enum
{
    FSDIO_HOST_INSTANCE_0 = 0,
    FSDIO_HOST_INSTANCE_1,

    FSDIO_HOST_INSTANCE_NUM
};

#define FSDIO_HOST_0_BASE_ADDR   0x28000000
#define FSDIO_HOST_1_BASE_ADDR   0x28001000

#define FSDIO_HOST_0_IRQ_NUM     104
#define FSDIO_HOST_1_IRQ_NUM     105

#define FSDIO_CLK_RATE_HZ          (200000000UL) /* 200MHz */

#ifdef __cplusplus
}
#endif

#endif // !